<template>
  <div class="container">
    <div id="chart"></div>
  </div>
</template>

<script setup>
import { onMounted } from "vue";
import G6 from "@antv/g6"; //在需要的js文件引入
onMounted(() => {
  init();
  initTree();
});

const data = {
  id: "root",
  label: "利息收入",
  subLabel: "3,283.456",
  ratio: 3,
  children: [
    {
      id: "child-b",
      label: "贷款余额",
      subLabel: "1,789,567",
      ratio: 23,
      increase: true,
      children: [
        {
          id: "child-b-b",
          label: "还款金额",
          subLabel: "595,557",
          ratio: 12,
          increase: true,
          children: [
            {
              id: "child-b-b-a",
              label: "还款期限",
              subLabel: "7",
              ratio: 23,
              increase: false,
              children: [
                {
                  id: "child-b-b-a-a",
                  label: "还款期限",
                  subLabel: "7",
                  ratio: 23,
                  increase: false,
                },
                {
                  id: "child-b-b-a-b",
                  label: "还款期限",
                  subLabel: "7",
                  ratio: 23,
                  increase: false,
                },
                {
                  id: "child-b-b-a-c",
                  label: "还款期限",
                  subLabel: "7",
                  ratio: 23,
                  increase: false,
                },
              ],
            },
          ],
        },
      ],
    },
  ],
};

const init = () => {
  // root node
  G6.registerNode("root", {
    draw: (cfg, group) => {
      const size = [100, 150];
      const keyShape = group.addShape("rect", {
        attrs: {
          width: size[0],
          height: size[1],
          x: -size[0] / 2,
          y: -size[1] / 2,
          fill: "rgb(19, 33, 92)",
          radius: 0,
        },
        draggable: true,
        name: "root-keyshape",
      });

      group.addShape('image', {
        attrs: {
          width: 98,
          height: 77,
          x: 0,
          y: 0,
          img: 'https://business-card-prod.oss-cn-shanghai.aliyuncs.com/xinhuan/bianzu1.png', // 设置图标
        },
        name: 'node-icon'
      })
      return keyShape;
    },
  });

  // level1 node
  G6.registerNode(
    "level1node",
    {
      draw: (cfg, group) => {
        const size = [50, 50];
        const keyShape = group.addShape("rect", {
          attrs: {
            width: size[0],
            height: size[1],
            x: -size[0] / 2,
            y: -size[1] / 2,
            fill: "rgb(213, 225, 247)",
            radius: 25,
          },
          draggable: true,
          name: "level1node-keyshape",
        });
        return keyShape;
      },
      update: undefined,
    },
    "rect"
  );

  // other node
  G6.registerNode(
    "othernode",
    {
      draw: (cfg, group) => {
        const size = [50, 50];
        const keyShape = group.addShape("rect", {
          attrs: {
            width: size[0],
            height: size[1],
            x: -size[0] / 2,
            y: -size[1] / 2,
            fill: "rgb(213, 225, 247)",
            radius: 25,
          },
          draggable: true,
          name: "level1node-keyshape",
        });
        // group.addShape("text", {
        //   attrs: {
        //     text: `${cfg.label}`,
        //     fill: "rgba(19, 33, 92, 0.65)",
        //     fontSize: 6,
        //     x: 0,
        //     y: 0,
        //     textAlign: "center",
        //   },
        //   draggable: true,
        //   name: "label-shape",
        // });
    
        return keyShape;
      },
      update: undefined,
    },
    "rect"
  );

  // edge
  G6.registerEdge(
    "round-poly",
    {
      getControlPoints: (cfg) => {
        const { startPoint, endPoint } = cfg;
        return [
          startPoint,
          {
            x: startPoint.x,
            y: endPoint.y,
          },
          endPoint,
        ];
      },
    },
    "polyline"
  );

  G6.Util.traverseTree(data, (subtree) => {
    if (subtree.level === undefined) subtree.level = 0;
    subtree.children?.forEach((child) => (child.level = subtree.level + 1));
    switch (subtree.level) {
      case 0:
        subtree.type = "root";
        break;
      case 1:
        subtree.type = "level1node";
        break;
      default:
        subtree.type = "othernode";
    }
  });
};

const initTree = () => {
  const width = document.getElementById("chart").scrollWidth || 800;
  const height = document.getElementById("chart").scrollHeight || 800;
  const graph = new G6.TreeGraph({
    container: "chart",
    width,
    height,
    fitView: true,
    layout: {
      type: "compactBox",
      direction: "LR",
      getHGap: function getVGap() {
        return 5;
      },
    },
    defaultEdge: {
      type: "round-poly",
      sourceAnchor: 0,
      targetAnchor: 1,
      style: {
        radius: 8,
        stroke: "#15A4FF",
      },
    },
    defaultNode: {
      anchorPoints: [
        [0.9, 0.5],
        [0, 0.5],
      ],
    },
    nodeStateStyles: {
      hover: {
        fill: "#fff",
        shadowBlur: 30,
        shadowColor: "#ddd",
      },
      operatorhover: {
        "operator-box": {
          opacity: 1,
        },
      },
    },
    modes: {
      default: ["zoom-canvas", "drag-canvas", "collapse-expand"],
    },
  });

  graph.on("node:mouseenter", (e) => {
    if (e.target.get("name")?.includes("operator")) {
      graph.setItemState(e.item, "operatorhover", true);
    } else {
      graph.setItemState(e.item, "hover", true);
    }
  });
  graph.on("node:mouseleave", (e) => {
    graph.setItemState(e.item, "operatorhover", false);
    graph.setItemState(e.item, "hover", false);
  });

  graph.data(data);
  graph.render();
};

// const init = () => {
//   G6.registerEdge(
//   "circle-running",
//   {
//     afterDraw(cfg, group) {
//       // get the first shape in the group, it is the edge's path here=
//       const shape = group.get("children")[0];
//       // the start position of the edge's path
//       const startPoint = shape.getPoint(0);

//       // add red circle shape
//       const circle = group.addShape("circle", {
//         attrs: {
//           x: startPoint.x,
//           y: startPoint.y,
//           fill: "#1890ff",
//           r: 3,
//         },
//         // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
//         name: "circle-shape",
//       });

//       // animation for the red circle
//       circle.animate(
//         (ratio) => {
//           // the operations in each frame. Ratio ranges from 0 to 1 indicating the prograss of the animation. Returns the modified configurations
//           // get the position on the edge according to the ratio
//           const tmpPoint = shape.getPoint(ratio);
//           // returns the modified configurations here, x and y here
//           return {
//             x: tmpPoint.x,
//             y: tmpPoint.y,
//           };
//         },
//         {
//           repeat: true, // Whether executes the animation repeatly
//           duration: 3000, // the duration for executing once
//         }
//       );
//     },
//   },
//   "cubic" // extend the built-in edge 'cubic'
// );
// };

// const data = {
//   nodes: [
//     {
//       id: "node1",
//       x: 100,
//       y: 100,
//       label: "Node 1",
//       color: "#15A4FF",
//       labelCfg: {
//         position: "top",
//       },
//     },
//     {
//       id: "node2",
//       x: 200,
//       y: 100,
//       color: "#15A4FF",
//       label: "Node 2",
//       labelCfg: {
//         position: "left",
//         offset: 10,
//       },
//     },
//     {
//       id: "node3",
//       x: 300,
//       y: 100,
//       color: "#15A4FF",
//       label: "Node 3",
//       labelCfg: {
//         position: "left",
//         offset: 10,
//       },
//     },
//     {
//       id: "node4",
//       x: 400,
//       y: 100,
//       color: "#15A4FF",
//       label: "Node 4",
//       labelCfg: {
//         position: "left",
//         offset: 10,
//       },
//     },
//   ],
//   edges: [
//     {
//       source: "node1",
//       target: "node2",
//     },
//     {
//       source: "node2",
//       target: "node3",
//     },
//     {
//       source: "node3",
//       target: "node4",
//     },
//   ],
// };

// const initTree = () => {
//   // const container = document.getElementById("chart");
//   const width = document.getElementById("chart").scrollWidth || 800;
//   const height = document.getElementById("chart").scrollHeight || 800;
//   const graph = new G6.Graph({
//     container: "chart",
//     width,
//     height,
//     defaultEdge: {
//       type: "circle-running",
//       style: {
//         lineWidth: 2,
//         stroke: "#bae7ff",
//       },
//     },
//   });
//   graph.data(data);
//   graph.render();
// };

// const data = {
//   id: "第一个",
//   label: "第一个",
//   children: [
//     {
//       id: "第二个",
//       label: "第二个",
//       children: [
//         { id: "第三个", label: "第三个" },
//         { id: "第四个", label: "第四个" },
//       ],
//     },
//     {
//       id: "第五个",
//       label: "第五个",
//       children: [
//         {
//           id: "第六个",
//           label: "第六个",
//           children: [{ id: "第七个", label: "第七个" }],
//         },
//       ],
//     },
//   ],
// };

// const initTree = () => {
//     // 画布宽高
//     const width = document.getElementById('chart').scrollWidth || 800;
//     const height = document.getElementById('chart').scrollHeight || 800;
//     const graph = new G6.TreeGraph({
//       // 图的  DOM 容器，可以传入该 DOM 的 id 或者直接传入容器的 HTML 节点对象。
//       container: 'chart',
//       // 指定画布宽度，单位为 'px'。
//       width,
//       // 指定画布高度，单位为 'px'。
//       height,
//       // 是否开启画布自适应。开启后图自动适配画布大小。
//       fitView: true,
//       //    v3.5.1 后支持。开启后，图将会被平移，图的中心将对齐到画布中心，但不缩放。优先级低于 fitView
//       fitCenter: true,
//       // 最小缩放比例
//       // minZoom: 1.5,
//       // 最大缩放比例
//       maxZoom: 1.5,
//       // 指定边是否连入节点的中心
//       linkCenter: true,
//       // 设置画布的模式
//       modes: {
//         default: [
//           {
//             // 只适用于树图，展开或收起子树
//             type: 'collapse-expand',
//             // trigger：收起和展开节点分组的方式。支持 'click' 和 'dblclick' 两种方式。默认为 'dblclick'，即双击。
//             trigger: 'click',
//             // onChange：收起或展开的回调函数。警告：V3.1.2 版本中将移除；
//             onChange: function onChange(item, collapsed) {
//               const data = item.get('model').data;
//               data.collapsed = collapsed;
//               return true;
//             },
//           },
//           // 拖拽画布；
//           'drag-canvas',
//           // 缩放画布；
//           'zoom-canvas',
//         ],
//       },
//       // 默认状态下节点的配置，比如 type, size, color。会被写入的 data 覆盖。
//       defaultNode: {
//         type: 'circle',
//         // size 是单个数字，表示直径
//         size: 26,
//         // 指定边连入节点的连接点的位置（相对于该节点而言），可以为空。例如: [0, 0]，代表节点左上角的锚点，[1, 1],代表节点右下角的锚点
//         anchorPoints: [
//           [0, 0.5],
//           [1, 0.5],
//         ],
//         // 节点样式
//         style: {
//           // 节点填充色
//           fill: '#C6E5FF',
//           // 节点的描边颜色，''就是没颜色的意思
//           stroke: '#5B8FF9',
//           // 那个小手
//           cursor:'pointer',
//         },
//         // Object 类型。配置标签文本
//         labelCfg: {
//           // 标签的样式属性。
//           style: {
//             // 文本颜色
//             fill: '#000000',
//             // 文本字体大小
//             fontSize: 14,
//           },
//         },
//       },
//       // 默认状态下边的配置，比如 type, size, color。会被写入的 data 覆盖。
//       defaultEdge: {
//         // 指定边的类型，可以是内置边的类型名称，也可以是自定义边的名称。默认为 'line'
//         type: 'cubic-vertical',
//         // 边的样式属性
//         style: {
//           // 边的颜色
//           stroke: '#A3B1BF',
//         },
//       },
//       // 布局配置项，使用 type 字段指定使用的布局方式
//       layout: {
//         // 布局名称
//         type: 'compactBox',
//         // layout 的方向。
//         direction: 'TB', // H / V / LR / RL / TB / BT
//         // 下面的参数都是一个节点，当存在某些奇葩点节点的时候，可以通过以下控制
//         // 节点 id 的回调函数
//         getId: function getId(d) {
//           return d.id;
//         },
//         // 节点高度的回调函数
//         getHeight: function getHeight() {
//           return 16;
//         },
//         // 节点宽度的回调函数
//         getWidth: function getWidth() {
//           return 16;
//         },
//         // 节点纵向间距的回调函数
//         getVGap: function getVGap() {
//           return 40;
//         },
//         // 节点横向间距的回调函数
//         getHGap: function getHGap() {
//           return 70;
//         },
//       },
//       // 动画
//       animate: true,
//     });
//     // 设置各个节点样式及其他配置，以及在各个状态下节点的 KeyShape 的样式
//     // 该方法必须在 render 之前调用，否则不起作用
//     // 使用 graph.node(nodeFn) 配置 > 数据中动态配置 > 实例化图时全局配置
//     graph.node(function (node) {
//       return {
//         label: node.label,
//         labelCfg: {
//           position: node.children && node.children.length > 0 ? 'top' : 'bottom',
//           offset: 5,
//           style: {
//             textAlign: 'center',
//           },
//         },
//       };
//     });
//     // 初始化的图数据
//     graph.data(data);
//     // 根据提供的数据渲染视图。
//     graph.render();
//     // 让画布内容适应视口
//     graph.fitView();
//   };
</script>

<style lang="less" scoped>
.container {
  #chart {
    width: 100%;
    background-color: antiquewhite;
    height: 800px;
  }
}
</style>
